﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;

namespace Quebec.Silverlight.Utilities
{
	public class RichTextBoxParser
	{
		private string markedUpText;
		private List<string> parts;
		private RichTextBox doc;

		[DefaultValue(12)]
		public static int FontSize
		{
			get;
			set;
		}
		[DefaultValue("Arial")]
		public static string FontFamily
		{
			get;
			set;
		}
		[DefaultValue(TextAlignment.Left)]
		public TextAlignment TextAlignment
		{
			get;
			set;
		}

		public RichTextBoxParser()
		{
			SetDefaults();
		}

		public RichTextBoxParser(string markedUpText)
		{
			this.markedUpText = markedUpText;
			parts = markedUpText.Split(new char[] { '{', '}' }).ToList();
			SetDefaults();
		}

		void SetDefaults()
		{
			FontSize = 12;
			FontFamily = "Arial";
			TextAlignment = TextAlignment.Left;
		}

		public void BuildRichTextBox()
		{
			doc = new RichTextBox();
			doc.Padding = new Thickness(0);
			Paragraph paragraph = BuildParagraph();
			paragraph.TextAlignment = TextAlignment;
			doc.Blocks.Add(paragraph);
		}

		public Paragraph BuildParagraph()
		{
			return BuildParagraph(parts);
		}

		public static Paragraph BuildParagraph(string parts)
		{
			return BuildParagraph(parts.Split(new char[] { '{', '}' }).ToList());
		}

		public static Paragraph BuildParagraph(List<string> parts)
		{
			Paragraph paragraph = new Paragraph();

			foreach (var part in parts)
			{
				//PARAGRAPH, e.g. "{p:}"
				if (part.StartsWith("p:"))
				{
					string text = part.ChopLeft("p:");
					paragraph.Inlines.Add(new LineBreak());
				}
				//ITALIC, e.g. "{i:this is italic}"
				else if (part.StartsWith("i:"))
				{
					string text = part.ChopLeft("i:");
					Run run = AddPart(paragraph, text);
					run.FontStyle = FontStyles.Italic;
				}
				//BOLD, e.g. "{b:this is bold}"
				else if (part.StartsWith("b:"))
				{
					string text = part.ChopLeft("b:");
					Run run = AddPart(paragraph, text);
					run.FontWeight = FontWeights.Bold;
				}
				//EXAMPLE TEXT, e.g. "{ex:this is an example}"
				else if (part.StartsWith("ex:"))
				{
					string text = part.ChopLeft("ex:");
					Run run = AddPart(paragraph, text);
					run.FontWeight = FontWeights.Bold;
					run.Foreground = new SolidColorBrush(Colors.Brown);
				}
				//HYPERLINK, e.g. "{link:google>>>http://www.google.com}"
				else if (part.StartsWith("link:"))
				{
					string text = part.ChopLeft("link:");
					List<string> pieces = text.SplitWithStringSeparator(">>>");
					string linkText = pieces[0];
					string linkUrl = pieces[1];
					Run run = new Run();
					run.Text = linkText;
					if(FontSize > 0)
						run.FontSize = FontSize;
					if(string.IsNullOrEmpty(FontFamily) == false)
						run.FontFamily = new FontFamily(FontFamily);
					run.Foreground = new SolidColorBrush(Colors.Blue);
					Hyperlink hl = new Hyperlink();
					hl.Inlines.Add(run);
					hl.NavigateUri = new Uri(linkUrl);
					hl.Foreground = new SolidColorBrush(Colors.Blue);
					paragraph.Inlines.Add(hl);
				}
				else
				{
					Run run = AddPart(paragraph, part);
				}
			}

			return paragraph;
		}

		static Run AddPart(Paragraph paragraph, string text)
		{
			Run run = new Run();
			run.Text = text;
			paragraph.Inlines.Add(run);
			if (FontSize > 0)
				run.FontSize = FontSize;
			if (string.IsNullOrEmpty(FontFamily) == false)
				run.FontFamily = new FontFamily(FontFamily);
			return run;
		}

		public RichTextBox GetBuiltRichTextBox()
		{
			return doc;
		}

		public static RichTextBox GetRichTextBox(string markedUpText)
		{
			RichTextBoxParser fdp = new RichTextBoxParser(markedUpText);
			fdp.BuildRichTextBox();
			return fdp.GetBuiltRichTextBox();
		}
	}

	public static class StringHelpers
	{
		public static string ChopLeft(this string line, string removeThis)
		{
			int removeThisLength = removeThis.Length;
			if (line.Length >= removeThisLength)
			{
				if (line.StartsWith(removeThis))
					return line.Substring(removeThisLength, line.Length - removeThisLength);
				else
					return line;
			}
			else
				return line;
		}

		public static List<string> SplitWithStringSeparator(this string line, string separator)
		{
			return line.Split(new string[] { separator }, StringSplitOptions.None).ToList();
		}
	}
}
